﻿using Dapper;
using JX.Core;
using JX.Core.Entity;
using JX.Infrastructure.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace JX.Application
{
	public partial class UserGroupsServiceAppDapper : ServiceAppDapper<UserGroupsEntity>, IUserGroupsServiceAppDapper
	{
		private char[] split = new char[] { ',' };

		#region 仓储接口
		private readonly IUsersRepositoryDapper _UsersRepository;
		private readonly IGroupFieldPermissionsRepositoryDapper _GroupFieldPermissionsRepository;
		private readonly IGroupNodePermissionsRepositoryDapper _GroupNodePermissionsRepository;
		private readonly IGroupSpecialPermissionsRepositoryDapper _GroupSpecialPermissionsRepository;
		private readonly ILogRepositoryDapper _LogRepository;
		/// <summary>
		/// 构造器注入
		/// </summary>
		/// <param name="repository"></param>
		/// <param name="usersRepository"></param>
		/// <param name="groupFieldPermissionsRepository"></param>
		/// <param name="groupNodePermissionsRepository"></param>
		/// <param name="groupSpecialPermissionsRepository"></param>
		/// <param name="logRepository"></param>
		public UserGroupsServiceAppDapper(IUserGroupsRepositoryDapper repository,
			IUsersRepositoryDapper usersRepository,
			IGroupFieldPermissionsRepositoryDapper groupFieldPermissionsRepository,
			IGroupNodePermissionsRepositoryDapper groupNodePermissionsRepository,
			IGroupSpecialPermissionsRepositoryDapper groupSpecialPermissionsRepository,
			ILogRepositoryDapper logRepository) : base(repository)
		{
			m_repository = repository;
			_UsersRepository = usersRepository;
			_GroupFieldPermissionsRepository = groupFieldPermissionsRepository;
			_GroupNodePermissionsRepository = groupNodePermissionsRepository;
			_GroupSpecialPermissionsRepository = groupSpecialPermissionsRepository;
			_LogRepository = logRepository;
		}
		#endregion

		#region 是否存在
		/// <summary>
		/// 判断会员组是否存在
		/// </summary>
		/// <param name="groupName">会员组名称</param>
		/// <returns></returns>
		public bool UserGroupIsExist(string groupName)
		{
			return m_repository.IsExist(p => p.GroupName == groupName);
		}
		/// <summary>
		/// 检查会员组中是否存在会员
		/// </summary>
		/// <param name="groupID"></param>
		/// <returns></returns>
		public bool ExistsUsersByGroupId(int groupID)
		{
			return _UsersRepository.IsExist(p => p.GroupID == groupID);
		}
		#endregion

		#region 删除会员组和相关权限
		/// <summary>
		/// 通过主键删除会员组。会员组中存在会员不能删除。
		/// 1、删除字段的权限设置。
		/// 2、删除节点的权限设置。
		/// 3、删除专题的权限设置。
		/// 4、删除会员组的权限设置。
		/// </summary>
		/// <param name="groupID"></param>
		/// <returns></returns>
		public async Task<bool> DeleteFullAsync(int groupID)
		{
			if (groupID <= 0)
			{
				return false;
			}
			if (ExistsUsersByGroupId(groupID))
				return false;
			await DeleteFieldPermissionFromGroup(groupID);
			await DeleteNodePermissionFromGroupAsync(groupID);
			await DeleteSpecialPermissionFromGroup(groupID);
			return await DeleteAsync(p => p.GroupID == groupID);
		}

		/// <summary>
		/// 移除指定会员组的所有专题权限
		/// </summary>
		/// <param name="groupID">会员组ID，小于等于0表示所有会员组，-2表示匿名会员组</param>
		/// <param name="specialId">专题ID，小于等于0表示所有专题</param>
		/// <param name="operateCode">权限码</param>
		/// <param name="idType">权限类型 0：单独设置会员权限；1：继承自会员组权限；</param>
		/// <returns></returns>
		public async Task<bool> DeleteSpecialPermissionFromGroup(int groupID = 0, int specialId = 0, OperateCode operateCode = OperateCode.None, int idType = 1)
		{
			string strCode = "";
			if (operateCode != OperateCode.None)
			{
				strCode = ((int)operateCode).ToString();
			}
			string strSpecialID = "";
			if (specialId > 0)
			{
				strSpecialID = specialId.ToString();
			}
			Expression<Func<GroupSpecialPermissionsEntity, bool>> predicate = p => true;
			if ((groupID > 0) || (groupID == -2))
			{
				predicate = predicate.And(p => p.GroupID == groupID);
			}
			if (!string.IsNullOrEmpty(strSpecialID))
			{
				var arrNodeID = strSpecialID.Split(',');
				predicate = predicate.And(p => arrNodeID.Contains(p.SpecialID.ToString()));
			}
			if (!string.IsNullOrEmpty(strCode))
			{
				predicate = predicate.And(p => p.OperateCode == strCode);
			}
			if (idType >= 0)
			{
				predicate = predicate.And(p => p.IDType == idType);
			}
			return await _GroupSpecialPermissionsRepository.DeleteAsync(predicate);
		}
		#endregion

		#region 会员组－节点权限管理
		/// <summary>
		/// 添加节点权限到会员组
		/// </summary>
		/// <param name="groupId"></param>
		/// <param name="nodeIdAndOperateCode">节点ID与权限码的集合体，多个内容用“,”分隔（例：-2:101005001,-2:101005002）</param>
		/// <param name="idType">权限类型 0：单独设置会员权限；1：继承自会员组权限；</param>
		/// <returns></returns>
		public async Task<bool> AddNodePermissionToUserGroup(int groupId, string nodeIdAndOperateCode, int idType = 1)
		{
			if (groupId <= 0 && groupId != -2)
			{
				return false;
			}
			if (string.IsNullOrWhiteSpace(nodeIdAndOperateCode))
				return false;

			var arrNodeIdAndOperateCode = nodeIdAndOperateCode.Split(split, StringSplitOptions.RemoveEmptyEntries);
			arrNodeIdAndOperateCode = StringHelper.RemoveRepeatItem(arrNodeIdAndOperateCode);
			foreach (string strItem in arrNodeIdAndOperateCode)
			{
				if (!string.IsNullOrWhiteSpace(strItem))
				{
					var arrItem = strItem.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
					var nodeID = DataConverter.CLng(arrItem[0]);
					var operateCodes = arrItem[1];

					await _GroupNodePermissionsRepository.AddAsync(new GroupNodePermissionsEntity() { GroupID = groupId, OperateCode = operateCodes, NodeID = nodeID, IdType = idType });
				}
			}
			return true;
		}
		/// <summary>
		/// 移除指定会员组的所有节点权限
		/// </summary>
		/// <param name="groupID">会员组ID，小于等于0表示所有会员组，-2表示匿名会员组</param>
		/// <param name="nodeId">节点ID，小于等于-3表示所有节点</param>
		/// <param name="operateCode">权限码</param>
		/// <param name="idType">权限类型 0：单独设置会员权限；1：继承自会员组权限；</param>
		/// <returns></returns>
		public bool DeleteNodePermissionFromGroup(int groupID = 0, int nodeId = -3, OperateCode operateCode = OperateCode.None, int idType = 1)
		{
			string strCode = "";
			if (operateCode != OperateCode.None)
			{
				strCode = ((int)operateCode).ToString();
			}
			string strNodeID = "";
			if (nodeId > -3)
			{
				strNodeID = nodeId.ToString();
			}
			Expression<Func<GroupNodePermissionsEntity, bool>> predicate = p => true;
			if ((groupID > 0) || (groupID == -2))
			{
				predicate = predicate.And(p => p.GroupID == groupID);
			}
			if (!string.IsNullOrEmpty(strNodeID))
			{
				var arrNodeID = strNodeID.Split(',');
				predicate = predicate.And(p => arrNodeID.Contains(p.NodeID.ToString()));
			}
			if (!string.IsNullOrEmpty(strCode))
			{
				predicate = predicate.And(p => p.OperateCode == strCode);
			}
			if (idType >= 0)
			{
				predicate = predicate.And(p => p.IdType == idType);
			}
			return _GroupNodePermissionsRepository.Delete(predicate);
		}
		/// <summary>
		/// 移除指定会员组的所有节点权限
		/// </summary>
		/// <param name="groupID">会员组ID，小于等于0表示所有会员组，-2表示匿名会员组</param>
		/// <param name="nodeId">节点ID，小于等于-3表示所有节点</param>
		/// <param name="operateCode">权限码</param>
		/// <param name="idType">权限类型 0：单独设置会员权限；1：继承自会员组权限；</param>
		/// <returns></returns>
		public async Task<bool> DeleteNodePermissionFromGroupAsync(int groupID = 0, int nodeId = -3, OperateCode operateCode = OperateCode.None, int idType = 1)
		{
			string strCode = "";
			if (operateCode != OperateCode.None)
			{
				strCode = ((int)operateCode).ToString();
			}
			string strNodeID = "";
			if (nodeId > -3)
			{
				strNodeID = nodeId.ToString();
			}
			Expression<Func<GroupNodePermissionsEntity, bool>> predicate = p => true;
			if ((groupID > 0) || (groupID == -2))
			{
				predicate = predicate.And(p => p.GroupID == groupID);
			}
			if (!string.IsNullOrEmpty(strNodeID))
			{
				var arrNodeID = strNodeID.Split(',');
				predicate = predicate.And(p => arrNodeID.Contains(p.NodeID.ToString()));
			}
			if (!string.IsNullOrEmpty(strCode))
			{
				predicate = predicate.And(p => p.OperateCode == strCode);
			}
			if (idType >= 0)
			{
				predicate = predicate.And(p => p.IdType == idType);
			}
			return await _GroupNodePermissionsRepository.DeleteAsync(predicate);
		}

		/// <summary>
		/// 获取指定会员组、指定节点的权限列表
		/// </summary>
		/// <param name="groupId">会员组ID，小于等于0表示所有会员组，-2表示匿名会员组</param>
		/// <param name="nodeId">节点ID，小于等于-3表示所有节点，-2表示首页节点</param>
		/// <param name="operateCode">权限码</param>
		/// <param name="idType">权限类型 0：单独设置会员权限；1：继承自会员组权限；</param>
		/// <returns></returns>
		public async Task<IList<GroupNodePermissionsEntity>> GetNodePermissionsById(int groupId = 0, int nodeId = -3, OperateCode operateCode = OperateCode.None, int idType = 1)
		{
			Expression<Func<GroupNodePermissionsEntity, bool>> predicate = p => true;
			if (groupId > 0 || groupId == -2)
			{
				predicate = predicate.And(p => p.GroupID == groupId);
			}
			if (nodeId >= -2)
			{
				predicate = predicate.And(p => p.NodeID == nodeId);
			}
			if (operateCode != OperateCode.None)
			{
				string strCode = ((int)operateCode).ToString();
				predicate = predicate.And(p => p.OperateCode == strCode);
			}
			if (idType >= 0)
			{
				predicate = predicate.And(p => p.IdType == idType);
			}
			var entityList = await _GroupNodePermissionsRepository.GetListAsync(predicate);
			return entityList.AsList();
		}
		#endregion

		#region 会员组－模型字段权限管理
		/// <summary>
		/// 为指定用户组集添加指定模型字段指定操作权限
		/// </summary>
		/// <param name="groupIds">会员组ID，多个ID用“,”分隔</param>
		/// <param name="modelId">模型ID</param>
		/// <param name="fieldName">字段名</param>
		/// <param name="operateCode">权限码</param>
		/// <param name="idType">会员权限类型 0：单独设置会员权限；1：继承自会员组权限；</param>
		/// <returns></returns>
		public async Task<bool> AddFieldPermissionToUserGroup(string groupIds, int modelId, string fieldName, OperateCode operateCode, int idType)
		{
			if (string.IsNullOrEmpty(fieldName) || (idType < 0) || (modelId <= 0))
			{
				return false;
			}
			await DeleteFieldPermissionFromGroup(0, modelId, fieldName, idType);
			foreach (string str in groupIds.Split(split, StringSplitOptions.RemoveEmptyEntries))
			{
				await _GroupFieldPermissionsRepository.AddAsync(new GroupFieldPermissionsEntity() { GroupID = str.ToInt32(), OperateCode = ((int)operateCode).ToString(), ModelID = modelId, FieldName = fieldName, IdType = idType });
			}
			return true;
		}
		/// <summary>
		/// 添加模型字段权限到会员组
		/// </summary>
		/// <param name="groupId"></param>
		/// <param name="operateCodes">权限码</param>
		/// <param name="modelIdAndFieldName">模型ID与字段名的集合体，多个内容用“,”分隔（例：11:FieldName,11:FieldName1）</param>
		/// <param name="idType">权限类型 0：单独设置会员权限；1：继承自会员组权限；</param>
		/// <returns></returns>
		public async Task<bool> AddFieldPermissionToUserGroup(int groupId, OperateCode operateCodes, string modelIdAndFieldName, int idType = 1)
		{
			if (groupId <= 0 && groupId != -2)
			{
				return false;
			}
			if (string.IsNullOrWhiteSpace(modelIdAndFieldName))
				return false;

			var arrModelIdAndFieldName = modelIdAndFieldName.Split(split, StringSplitOptions.RemoveEmptyEntries);
			arrModelIdAndFieldName = StringHelper.RemoveRepeatItem(arrModelIdAndFieldName);
			foreach (string strItem in arrModelIdAndFieldName)
			{
				if (!string.IsNullOrEmpty(strItem))
				{
					var arrItem = strItem.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
					var modelID = DataConverter.CLng(arrItem[0]);
					var fieldName = arrItem[1];

					await _GroupFieldPermissionsRepository.AddAsync(new GroupFieldPermissionsEntity() { GroupID = groupId, OperateCode = ((int)operateCodes).ToString(), ModelID = modelID, FieldName = fieldName, IdType = idType });
				}
			}
			return true;
		}
		/// <summary>
		/// 移除指定会员组的所有模型字段权限
		/// </summary>
		/// <param name="groupID">会员组ID，小于等于0表示所有会员组，-2表示匿名会员组</param>
		/// <param name="modelID">模型ID：小于等于0表示全部模型；</param>
		/// <param name="fieldName">字段名称：空或NULL表示全部字段；</param>
		/// <param name="idType">权限类型：小于0表示全部；0：单独设置会员权限；1：继承自会员组权限；</param>
		/// <returns></returns>
		public async Task<bool> DeleteFieldPermissionFromGroup(int groupID = 0, int modelID = 0, string fieldName = "", int idType = 1)
		{
			Expression<Func<GroupFieldPermissionsEntity, bool>> predicate = p => true;
			if ((groupID > 0) || (groupID == -2))
			{
				predicate = predicate.And(p => p.GroupID == groupID);
			}
			if (modelID > 0)
			{
				predicate = predicate.And(p => p.ModelID == modelID);
			}
			if (!string.IsNullOrWhiteSpace(fieldName))
			{
				predicate = predicate.And(p => p.FieldName == fieldName);
			}
			if (idType >= 0)
			{
				predicate = predicate.And(p => p.IdType == idType);
			}
			return await _GroupFieldPermissionsRepository.DeleteAsync(predicate);
		}
		/// <summary>
		/// 获取指定会员组、指定模型的字段权限列表
		/// </summary>
		/// <param name="groupId">会员组ID，小于等于0表示所有会员组，-2表示匿名会员组</param>
		/// <param name="modelId">模型ID，小于等于0表示所有模型</param>
		/// <param name="idType">权限类型 0：单独设置会员权限；1：继承自会员组权限；</param>
		/// <param name="fieldName">字段名</param>
		/// <returns></returns>
		public async Task<IList<GroupFieldPermissionsEntity>> GetFieldPermissionsById(int groupId = 0, int modelId = 0, int idType = 1, string fieldName = "")
		{
			Expression<Func<GroupFieldPermissionsEntity, bool>> predicate = p => true;
			if (groupId > 0 || groupId == -2)
			{
				predicate = predicate.And(p => p.GroupID == groupId);
			}
			if (modelId > 0)
			{
				predicate = predicate.And(p => p.ModelID == modelId);
			}
			if (idType >= 0)
			{
				predicate = predicate.And(p => p.IdType == idType);
			}
			if (!string.IsNullOrEmpty(fieldName))
			{
				predicate = predicate.And(p => p.FieldName == fieldName);
			}
			var entityList = await _GroupFieldPermissionsRepository.GetListAsync(predicate);
			return entityList.ToList();
		}
		/// <summary>
		///  获取当前登录会员对指定模型字段，指定权限有权操作的用户组ID集
		/// </summary>
		/// <param name="operateCode"></param>
		/// <param name="modelId"></param>
		/// <param name="fieldName"></param>
		/// <returns></returns>
		public async Task<IList<int>> GetGroupIDListByOperateCodeFieldName(OperateCode operateCode, int modelId, string fieldName)
		{
			int idType = 0;
			var claim = MyHttpContext.Current.User.FindFirst("IsInheritGroupRole");
			if (claim != null)
			{
				if(claim.Value.ToBoolean())
				{
					idType = 1;
				}
			}
			Expression<Func<GroupFieldPermissionsEntity, bool>> predicate = p => p.IdType == idType;
			if (operateCode != OperateCode.None)
			{
				var enumValue = ((int)operateCode).ToString();
				predicate = predicate.And(p => p.OperateCode == enumValue);
			}
			if (modelId > 0)
			{
				predicate = predicate.And(p => p.ModelID == modelId);
			}
			if (!string.IsNullOrEmpty(fieldName))
			{
				predicate = predicate.And(p => p.FieldName == fieldName);
			}
			var entityList = await _GroupFieldPermissionsRepository.GetAllDataAsync<int?>(predicate:predicate,selector:p=>p.GroupID);
			List<int> list = new List<int>();
			foreach (int item in entityList)
			{
				list.Add(item);
			}
			return list;
		}
		/// <summary>
		/// 检查当前会员是否对指定模型指定字段有操作权限
		/// </summary>
		/// <param name="operateCode"></param>
		/// <param name="modelId"></param>
		/// <param name="fieldName"></param>
		/// <returns></returns>
		public async Task<bool> AccessCheckFieldPermission(OperateCode operateCode, int modelId, string fieldName)
		{
			var groupIDs = await GetGroupIDListByOperateCodeFieldName(operateCode, modelId, fieldName);
			return CheckRole(groupIDs);
		}
		#endregion

		#region 其他
		/// <summary>
		/// 计算会员组集合里的会员总数
		/// </summary>
		/// <param name="userGroupsList"></param>
		public void CountUserNumber(IList<UserGroupsEntity> userGroupsList)
		{
			for (int i = 0; i < userGroupsList.Count; i++)
			{
				userGroupsList[i].UserInGroupNumber = _UsersRepository.GetCount(p => p.GroupID == userGroupsList[i].GroupID);
			}
		}

		/// <summary>
		/// 判断当前用户是否属于指定的组列表
		/// </summary>
		/// <param name="groupIdList"></param>
		/// <returns></returns>
		private bool CheckRole(IList<int> groupIdList)
		{
			var claim = MyHttpContext.Current.User.FindFirst("IdByIdType");
			foreach (int num in groupIdList)
			{
				if (num != 0 && num == claim.Value.ToInt32())
				{
					return true;
				}
			}
			return false;
		}
		#endregion
	}
}
